package com.lp.business.function;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

import javax.servlet.http.HttpServletResponse;
/**
 * 下载工具包
 * @author lp
 *
 */
public class DownloadUtil {
	/**
	 * 流输出单文件
	 * @param response
	 * @param filename	文件名
	 * @param filePath 	文件路径
	 * @param useBuffer	是否使用缓冲流输出
	 * @throws IOException
	 */
	public static void outputFile(HttpServletResponse response, String filename, String filePath,boolean useBuffer,boolean isNetFile,boolean isOpenOnLine) throws IOException {
		response.setContentType("text/html; charset=UTF-8"); // 设置编码字符
		response.setContentType("application/octet-stream"); // 设置内容类型为下载类型
		//response.setContentType("application/x-msdownload");
		response.setHeader("Content-disposition", "attachment;filename=" + filename);// 设置下载的文件名称
		
		response.reset(); // 非常重要
        if (isOpenOnLine) { // 在线打开方式
            URL u = new URL("file:///" + filePath);
            response.setContentType(u.openConnection().getContentType());
            response.setHeader("Content-disposition", "inline; filename="  + filename);
            useBuffer=false;//如果在线预览，则不能用buffer缓冲
        }
		OutputStream out = response.getOutputStream(); // 创建页面返回方式为输出流，会自动弹出下载框
		//根据是否是网络文件，生成不同的输入流
		InputStream is = null;
		if(isNetFile){
			URL url = new URL(filePath);
		    URLConnection conn = url.openConnection();
		    is = conn.getInputStream();
		}else{
			is = new FileInputStream(filePath);
		}
		//根据是否使用缓冲流，进行不同的输出
		if(useBuffer){//使用缓冲流,则创建文件缓冲输入流
			BufferedInputStream bis = new BufferedInputStream(is);
			byte[] buffer = new byte[bis.available()];
			bis.read(buffer);// 从输入流中读取不受阻塞 ,读取数据文件
			bis.close();
			out.write(buffer);
		}else{
			byte[] buffer = new byte[2048];
			int size = 0;// 设置每次读取数据大小，即缓存大小
			while ((size = is.read(buffer)) != -1) {// 用于循环读取数据，如果数据已经读取完了，则会返回-1
				out.write(buffer, 0, size);// 将每次读取到的数据写入客户端
			}
			is.close();
		}
		out.close();// 关闭输出流
	}

	/**
	 * 流输出压缩文件包
	 * @param response
	 * @param filename		文件名
	 * @param zipFilePath	打包文件路径
	 * @param filePaths		文件路径列表
	 * @throws Exception
	 */
	public static void outputZip(HttpServletResponse response, String filename, String zipFilePath, List<String> filePaths)
			throws Exception {
		response.setContentType("text/html; charset=UTF-8"); // 设置编码字符
		response.setContentType("application/octet-stream"); // 设置内容类型为下载类型
		response.setHeader("Content-disposition", "attachment;filename=" + filename);// 设置下载的文件名称
		OutputStream out = response.getOutputStream();
		// 压缩文件
		File zip = new File(zipFilePath);
		if (!zip.exists()) {
			zip.createNewFile();
		}
		// 创建zip文件输出流
		ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(zip));
		zipFile(zipFilePath, filePaths, zos);
		zos.close();
		// 将打包后的文件写到客户端，输出的方法同上，使用缓冲流输出
		BufferedInputStream bis = new BufferedInputStream(new FileInputStream(zipFilePath));
		byte[] buff = new byte[bis.available()];
		bis.read(buff);
		bis.close();
		out.write(buff); // 输出数据文件
		out.flush();// 释放缓存
		out.close();// 关闭输出流

	}

	/**
	 * 压缩文件
	 * @param zipFilePath 临时压缩文件完整路径
	 * @param filePaths 需要压缩的文件路径集合
	 */
	public static void zipFile(String zipFilePath, List<String> filePaths, ZipOutputStream zos) throws Exception{
		// 循环读取文件路径集合，获取每一个文件的路径
		for (String filePath : filePaths) {
			File inputFile = new File(filePath); // 根据文件路径创建文件
			if (inputFile.exists()) { // 判断文件是否存在
				if (inputFile.isFile()) { // 判断是否属于文件，还是文件夹
					// 创建输入流读取文件
					BufferedInputStream bis = new BufferedInputStream(new FileInputStream(inputFile));
					// 将文件写入zip内，即将文件进行打包
					zos.putNextEntry(new ZipEntry(inputFile.getName()));
					// 写入文件的方法，同上
					int size = 0;
					byte[] buffer = new byte[1024]; // 设置读取数据缓存大小
					while ((size = bis.read(buffer)) > 0) {
						zos.write(buffer, 0, size);
					}
					// 关闭输入输出流
					zos.closeEntry();
					bis.close();
				} else { // 如果是文件夹，则使用穷举的方法获取文件，写入zip
					File[] files = inputFile.listFiles();
					List<String> filePathsTem = new ArrayList<String>();
					for (File fileTem : files) {
						filePathsTem.add(fileTem.toString());
					}
					zipFile(zipFilePath, filePathsTem, zos);
				}
			}
		}
	}

}
